home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2001 December / pcwk12201b.iso / Wersje pelne i specjalne / Winamp 2.77 i 3.0beta / wasabi-sdk_beta1.exe / studio / common / framewnd.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  16.6 KB  |  643 lines

  1. /*
  2.  
  3.   Nullsoft WASABI Source File License
  4.  
  5.   Copyright 1999-2001 Nullsoft, Inc.
  6.  
  7.     This software is provided 'as-is', without any express or implied
  8.     warranty.  In no event will the authors be held liable for any damages
  9.     arising from the use of this software.
  10.  
  11.     Permission is granted to anyone to use this software for any purpose,
  12.     including commercial applications, and to alter it and redistribute it
  13.     freely, subject to the following restrictions:
  14.  
  15.     1. The origin of this software must not be misrepresented; you must not
  16.        claim that you wrote the original software. If you use this software
  17.        in a product, an acknowledgment in the product documentation would be
  18.        appreciated but is not required.
  19.     2. Altered source versions must be plainly marked as such, and must not be
  20.        misrepresented as being the original software.
  21.     3. This notice may not be removed or altered from any source distribution.
  22.  
  23.  
  24.   Brennan Underwood
  25.   brennan@nullsoft.com
  26.  
  27. */
  28.  
  29.  
  30. #include "framewnd.h"
  31. #include "notifmsg.h"
  32. #include "../studio/assert.h"
  33. #include "../studio/api.h"
  34. #include "canvas.h"
  35.  
  36. #define SNAP 4
  37.  
  38. FrameWnd::FrameWnd() {
  39. //  sizer = NULL;
  40.   nchild = 0;
  41.   for (int i = 0; i < MAXCHILD; i++) {
  42.     children[i] = NULL;
  43.     hidey[i] = 0;
  44.     windowshaded[i] = 0;
  45.   }
  46.   vert = DIVIDER_UNDEFINED;
  47.   divideside = SDP_FROMLEFT;
  48.   pullbarpos = PULLBAR_HALF;
  49.   minwidth = PULLBAR_QUARTER-PULLBAR_EIGHTH;
  50.   maxwidth = PULLBAR_HALF;
  51.   resizeable = 0;
  52.   slidemode = FRAMEWND_SQUISH;
  53.   prevpullbarpos = -1;
  54.  
  55.   MEMSET(&sizerRect, 0, sizeof(RECT));
  56.  
  57.   h_bitmap = "studio.framewnd.horizontaldivider";
  58.   v_bitmap = "studio.framewnd.verticaldivider";
  59.   h_grabber = "studio.framewnd.horizontalgrabber";
  60.   v_grabber = "studio.framewnd.verticalgrabber";
  61.   ws_bitmap = "studio.framewnd.windowshade";
  62. }
  63.  
  64. FrameWnd::~FrameWnd() {
  65.   if (getName() != NULL) {
  66.     StringPrintf buf("FrameWnd/ws,%s", getName());
  67.     api->setIntPrivate(buf, windowshaded[0]);
  68.   }
  69.   setName(NULL);
  70.   for (int i = 0; i < nchild; i++) delete children[i];
  71. }
  72.  
  73. int FrameWnd::onInit() {
  74.   int i;
  75.  
  76.   FRAMEWND_PARENT::onInit();
  77.  
  78.   ASSERT(vert != DIVIDER_UNDEFINED || nchild == 0);
  79.  
  80.   // have to set children for frame windows
  81.  
  82.   // fill in members
  83.   nchild = 0;
  84.  
  85.   // make children create their windows
  86.   for (i = 0; i < MAXCHILD; i++) {
  87.     if (children[i] != NULL) {
  88.       if (children[i]->init(this) != 0) {
  89.         children[i]->setParent(this);
  90.         nchild++;
  91.       }
  92.     }
  93.   }
  94.   prevpullbarpos = pullbarpos;
  95.   // size the fuckers
  96.   onResize();
  97.  
  98.   if (nchild >= MAXCHILD) {
  99.     int which = (divideside == SDP_FROMLEFT) ? 0 : 1;
  100.     children[which]->moveToFront();
  101.   }
  102.  
  103.   if (getName() != NULL) {
  104.     StringPrintf buf("FrameWnd/ws,%s", getName());
  105.     int ws = api->getIntPrivate(buf, /*children[0] && children[0]->childNotify(NULL, CHILD_WINDOWSHADE_CAPABLE)*/ 0);
  106.     if (ws) {
  107.       windowshade(0, !ws);
  108.       windowshade(0, ws);
  109.       pullbarpos = 0;
  110.     }
  111.   }
  112.  
  113.   return 1;
  114. }
  115.  
  116. int FrameWnd::getCursorType(int x, int y) {
  117.   if (y < getLabelHeight()) return BASEWND_CURSOR_POINTER;
  118.   if (vert == DIVIDER_HORIZONTAL) return BASEWND_CURSOR_NORTHSOUTH;
  119.   else return BASEWND_CURSOR_EASTWEST;
  120. }
  121.  
  122. int FrameWnd::setChildren(BaseWnd *newchild1, BaseWnd *newchild2) {
  123.   children[0] = newchild1;
  124.   children[1] = newchild2;
  125.   nchild = 0;
  126.   if (children[0] != NULL) nchild++;
  127.   if (children[1] != NULL) nchild++;
  128.  
  129.   ASSERTPR(nchild >= 1, "framewnd must have one or more children");
  130.  
  131.   onResize();
  132.   return nchild;
  133. }
  134.  
  135. BaseWnd *FrameWnd::enumChild(int which) {
  136.   if (which < 0 || which >= MAXCHILD) return NULL;
  137.   return children[which];
  138. }
  139.  
  140. int FrameWnd::childNotify(RootWnd *which, int msg, int param1, int param2) {
  141. //  ASSERT(which == children[0] || which == children[1] || which == NULL);
  142.   switch (msg) {
  143.     case CHILD_SETTITLEWIDTH:
  144.       if (pullbarpos == param1) return 0;
  145. //CUT      ASSERTPR(dividepostype == SDP_INPIXELS, "right now child windows can only set titlewidths if its an inpixels frame");
  146.       ASSERT(param1 >= 0);
  147.         if (which == children[0]) {
  148.           // children[1]->invalidate(); //FG> removed due to change in redraw layout
  149.           // children[1]->repaint();
  150.           ASSERT(divideside == SDP_FROMLEFT);
  151.         } else {
  152.           // children[0]->invalidate();
  153.           // children[0]->repaint();
  154.           ASSERT(divideside == SDP_FROMRIGHT);
  155.         }
  156.       pullbarpos = param1;
  157.       // do it
  158.       onResize();
  159.     return 1;
  160.  
  161.     case CHILD_HIDEYHIDEY:
  162.       if (which == children[0]) hidey[0] = 1;
  163.       else if (which == children[1]) hidey[1] = 1;
  164.       which->setVisible(FALSE);
  165.       onResize();
  166.     return 1;
  167.  
  168.     case CHILD_UNHIDEYHIDEY:
  169.       if (which == children[0]) hidey[0] = 0;
  170.       else if (which == children[1]) hidey[1] = 0;
  171.       which->setVisible(TRUE);
  172.       onResize();
  173.     return 1;
  174.  
  175.     case FRAMEWND_QUERY_SLIDE_MODE:
  176.       return getSlideMode();
  177.  
  178.     case FRAMEWND_SET_SLIDE_MODE:
  179.       setSlideMode((FrameWndSlideMode)param1);
  180.     break;
  181.     case CHILD_GOTFOCUS:
  182.     case CHILD_KILLFOCUS:
  183.       invalidateLabel();
  184.     break;
  185.   }
  186.  
  187.   return FRAMEWND_PARENT::childNotify(which, msg, param1, param2);
  188. }
  189.  
  190. int FrameWnd::forceFocus() {
  191.   if (!canShowFocus()) return 0;    // we aren't showing a label
  192.   int v = 0;
  193.   if (nchild > 0 && children[0] != NULL) {
  194.     if (!children[0]->canShowFocus()) v |= children[0]->gotFocus();
  195.   }
  196.   if (nchild > 1 && children[1] != NULL) {
  197.     if (!children[1]->canShowFocus()) v |= children[1]->gotFocus();
  198.   }
  199.   return v;
  200. }
  201.  
  202. void FrameWnd::setDividerType(FrameWndDividerType type) {
  203.   vert = type;
  204.   ASSERT(vert == DIVIDER_VERTICAL || vert == DIVIDER_HORIZONTAL);
  205.   onResize();
  206. }
  207.  
  208. FrameWndDividerType FrameWnd::getDividerType() {
  209.   return vert;
  210. }
  211.  
  212. int FrameWnd::ConvertPixToProp() {
  213.   RECT r;
  214.   int w;
  215.   getClientRect(&r);
  216.   if(vert == DIVIDER_VERTICAL) {
  217.     w = r.right-r.left;
  218.   } else {
  219.     w = r.bottom-r.top;
  220.   }
  221.   w = (pullbarpos * PULLBAR_FULL) / w;
  222.   return w;
  223. }
  224.  
  225. int FrameWnd::convertPropToPix(int prop) {
  226.   RECT r;
  227.   int w;
  228.  
  229.   getClientRect(&r);
  230.   if(vert == DIVIDER_VERTICAL) {
  231.     w = r.right-r.left;
  232.   } else {
  233.     w = r.bottom-r.top;
  234.   }
  235.   return (w * prop) / PULLBAR_FULL;
  236. }
  237.  
  238. int FrameWnd::setDividerPosNoCfg(int from, int pos) {
  239.   divideside = from;
  240.  
  241.   ASSERT(pos >= 0);
  242.   pullbarpos = pos;
  243.   onResize();
  244.   return 1;
  245. }
  246.  
  247. int FrameWnd::setDividerPos(int from, int pos) {
  248.   if (getName() != NULL) {
  249.     StringPrintf buf("FrameWnd/%s,p", getName());
  250.     pos = api->getIntPrivate(buf, pos);
  251.     if (pos <= 0) pos = 0;
  252.     else if (pos >= PULLBAR_FULL) pos = PULLBAR_FULL;
  253.   }
  254.   return setDividerPosNoCfg(from, pos);
  255. }
  256.  
  257. void FrameWnd::getDividerPos(int *from, int *pos) {
  258.   if (from != NULL) *from = divideside;
  259.   if (pos != NULL) *pos = pullbarpos;
  260. }
  261.  
  262. int FrameWnd::setResizeable(int is) {
  263.   int prev = resizeable;
  264.   resizeable = is;
  265.   return prev;
  266. }
  267.  
  268. void FrameWnd::setMinWidth(int min) {
  269.   ASSERT(min >= 0);
  270.   minwidth = min;
  271. }
  272.  
  273. void FrameWnd::setSlideMode(FrameWndSlideMode mode) {
  274.   slidemode = mode;
  275.   onResize();
  276. }
  277.  
  278. FrameWndSlideMode FrameWnd::getSlideMode() {
  279.   return slidemode;
  280. }
  281.  
  282. int FrameWnd::dragEnter(RootWnd *sourceWnd) {
  283.   BaseWnd *ch = getWindowShadedChild();
  284.   if (ch == NULL) return FRAMEWND_PARENT::dragEnter(sourceWnd);
  285.   return ch->dragEnter(sourceWnd);
  286. }
  287.  
  288. int FrameWnd::dragOver(int x, int y, RootWnd *sourceWnd) {
  289.   BaseWnd *ch = getWindowShadedChild();
  290.   if (ch == NULL) return FRAMEWND_PARENT::dragOver(x, y, sourceWnd);
  291.   return ch->dragOver(-1, -1, sourceWnd);
  292. }
  293.  
  294. int FrameWnd::dragLeave(RootWnd *sourceWnd) {
  295.   BaseWnd *ch = getWindowShadedChild();
  296.   if (ch == NULL) return FRAMEWND_PARENT::dragLeave(sourceWnd);
  297.   return ch->dragLeave(sourceWnd);
  298. }
  299.  
  300. int FrameWnd::dragDrop(RootWnd *sourceWnd, int x, int y) {
  301.   BaseWnd *ch = getWindowShadedChild();
  302.   if (ch == NULL) return FRAMEWND_PARENT::dragDrop(sourceWnd, x, y);
  303.   return ch->dragDrop(sourceWnd, x, y);
  304. }
  305.  
  306. int FrameWnd::onResize() {
  307.   FRAMEWND_PARENT::onResize();
  308.   RECT r;
  309.   int sizerwidth = SIZERWIDTH;
  310.  
  311.   if (!isInited()) {
  312.     prevpullbarpos = pullbarpos;
  313.     return 1;    // no window to resize
  314.   }
  315.  
  316.   getClientRect(&r);
  317.  
  318.   ASSERT(nchild >= 0);
  319.   if (nchild == 0) {
  320.     prevpullbarpos = pullbarpos;
  321.     return 1;
  322.   }
  323.  
  324.   if (hidey[0] && hidey[1]) return 0;    // both windows are hiding
  325.  
  326.   // if we have only one child, it takes up all the room
  327.   if (hidey[0]) {
  328.     children[1]->resize(&r);
  329.     return 1;
  330.   } else if (hidey[1]) {
  331.     children[0]->resize(&r);
  332.     return 1;
  333.   }
  334.  
  335.   if (nchild == 1) {
  336.     if (children[0] != NULL) children[0]->resize(&r);
  337.     else if (children[1] != NULL) children[1]->resize(&r);
  338.     return 1;
  339.   }
  340.  
  341. #ifdef ASSERTS_ENABLED
  342.   for (int i = 0; i < nchild; i++) {
  343.     ASSERT(children[i] != NULL);
  344.   }
  345. #endif
  346.  
  347.   if (!resizeable) sizerwidth = 0;
  348.  
  349.   // resize the subwindows
  350.  
  351.   int w, h;
  352.   if (vert == DIVIDER_VERTICAL) {
  353.     w = r.right-r.left;
  354.     h = r.bottom-r.top;
  355.   } else {
  356.     w = r.bottom-r.top;
  357.     h = r.bottom-r.top;
  358.   }
  359.   int clientwidth = w;    // the logical width
  360.  
  361.   w = pullbarpos;
  362.  
  363.   if (divideside == SDP_FROMRIGHT) {
  364.     w = (clientwidth - w);
  365.   }
  366.  
  367.   RECT r1, r2;
  368.  
  369.   if (slidemode == FRAMEWND_COVER) { // cover mode
  370.  
  371.     ASSERTPR(vert == DIVIDER_VERTICAL, "finish implementing");
  372.  
  373.     if (divideside == SDP_FROMRIGHT) {
  374.       SetRect(&r1, r.left, r.top, r.right-r.left, r.bottom-r.top); //FG> delay resize
  375.       SetRect(&r2, r.left+w, r.top, r.left+clientwidth - w, r.bottom-r.top);
  376.     } else {
  377.       SetRect(&r1, r.left, r.top, r.left+w, r.bottom-r.top); //FG> delay resize
  378.       SetRect(&r2, r.left, r.top, r.right-r.left, r.bottom-r.top);
  379.     }
  380.  
  381.     sizerRect.top = r.top;
  382.     sizerRect.bottom = r.bottom;
  383.     sizerRect.left = w;
  384.     sizerRect.right = w+sizerwidth;
  385.  
  386.   } else { // squish mode
  387.     // left-right
  388.     if (vert == DIVIDER_VERTICAL) {
  389.       sizerRect.top = r.top;
  390.       sizerRect.bottom = r.bottom;
  391.       if (divideside == SDP_FROMLEFT) { // from left
  392.         SetRect(&r1, r.left, r.top, r.left+w, r.bottom-r.top);
  393.         SetRect(&r2, w+sizerwidth, r.top, (r.right-r.left)-(w+sizerwidth), r.bottom-r.top);
  394.         sizerRect.left = w;
  395.         sizerRect.right = sizerRect.left + sizerwidth;
  396.       } else {    // from right
  397.         SetRect(&r1, r.left, r.top, (r.left+w)-sizerwidth, r.bottom-r.top);
  398.         SetRect(&r2, w, r.top, (r.right-r.left)-w, r.bottom-r.top);
  399.         sizerRect.left = w-sizerwidth;
  400.         sizerRect.right = w;
  401.       }
  402.     } else {
  403.       // top-bottom
  404.       SetRect(&r1, r.left, r.top, r.right, r.top+w); //FG> delay resize
  405.       SetRect(&r2, r.left, r.top+w+sizerwidth, r.right-r.left, (r.bottom-r.top)-(w+sizerwidth));
  406.       sizerRect.top = w;
  407.       sizerRect.bottom = w+sizerwidth;
  408.       sizerRect.left = r.left;
  409.       sizerRect.right = r.right;
  410.     }
  411.   }
  412.  
  413.   //FG> Choose resizing order. optimizes redraw by avoiding temporary overlap of children
  414.   BOOL reverse = FALSE;
  415.   if (vert == DIVIDER_VERTICAL) {
  416.     RECT o;
  417.     children[0]->getNonClientRect(&o);
  418.     reverse = (r1.right > o.right);
  419.   } else {
  420.     RECT o;
  421.     children[0]->getNonClientRect(&o);
  422.     reverse = (r1.bottom > o.bottom);    
  423.   }
  424.  
  425.   //FG> actually resize children
  426.   if (reverse) {
  427.     children[1]->resize(r2.left, r2.top, r2.right, r2.bottom);
  428.     children[0]->resize(r1.left, r1.top, r1.right, r1.bottom);
  429.   } else {
  430.     children[0]->resize(r1.left, r1.top, r1.right, r1.bottom);
  431.     children[1]->resize(r2.left, r2.top, r2.right, r2.bottom);
  432.   }
  433.  
  434.   RECT ri = sizerRect;
  435. #if 0
  436.   if (vert == DIVIDER_HORIZONTAL) {
  437.     ri.left -= 2;
  438.     ri.right += 2;
  439.   } else {
  440.     ri.top -= 2;
  441.     ri.bottom += 2;
  442.   }
  443. #endif
  444.   invalidateRect(&ri);
  445.  
  446.   prevpullbarpos = pullbarpos;
  447.  
  448.   return 1;
  449. }
  450.  
  451. int FrameWnd::onPaint(Canvas *canvas) {
  452.  
  453.   RECT d;
  454.   getClientRect(&d);
  455.   if ((d.left >= d.right) || (d.top >= d.bottom)) {
  456.     return FRAMEWND_PARENT::onPaint(canvas);
  457.   }
  458.  
  459.   RECT cr;
  460. //  PaintBltCanvas paintcanvas;
  461.   PaintCanvas paintcanvas;
  462.  
  463.   // if only 1 child, we don't paint anything
  464.   if (nchild <= 1) return FRAMEWND_PARENT::onPaint(canvas);
  465.  
  466.   if (canvas == NULL) {
  467.     if (!paintcanvas.beginPaint(this)) return 0;
  468.     canvas = &paintcanvas;
  469.   }
  470.   FRAMEWND_PARENT::onPaint(canvas);
  471.  
  472.   getClientRect(&cr);
  473.  
  474.   if (resizeable) {
  475.     RECT r = sizerRect;
  476.     if (vert == DIVIDER_HORIZONTAL) {
  477.       r.left -= 2;
  478.       r.right += 2;
  479.     } else {
  480.       r.top -= 2;
  481.       r.bottom += 2;
  482.     }
  483.  
  484.     renderBaseTexture(canvas, r);
  485.     AutoSkinBitmap &bitmap = (vert == DIVIDER_VERTICAL) ? v_bitmap : h_bitmap;
  486.     bitmap.stretchToRectAlpha(canvas, &r);
  487.  
  488.     AutoSkinBitmap &grabber = (vert == DIVIDER_VERTICAL) ? v_grabber : h_grabber;
  489.     int h = sizerRect.bottom - sizerRect.top;
  490.     int gh = grabber.getHeight();
  491.     if (h > gh) {
  492.       RECT rr = sizerRect;
  493.       rr.top += (h - gh) / 2;
  494.       rr.bottom -= (h - gh) / 2;
  495.       grabber.stretchToRectAlpha(canvas, &rr);
  496.     }
  497.  
  498.     if (windowshaded[0]) {
  499.       RECT wr = cr;
  500.       if (vert == DIVIDER_VERTICAL) {
  501.         wr.right = r.left;
  502.       } else if (vert == DIVIDER_HORIZONTAL) {
  503.         wr.bottom = r.top;
  504.       }
  505.  
  506.       ws_bitmap.stretchToRect(canvas, &wr);
  507.     }
  508.  
  509.   }
  510.  
  511.   return 0;
  512. }
  513.  
  514. int FrameWnd::onLeftButtonDown(int x, int y) {
  515.   FRAMEWND_PARENT::onLeftButtonDown(x, y);
  516.   if (!resizeable) return 1;
  517.   POINT p = { x, y };
  518.   if (Std::pointInRect(&sizerRect, p)) {
  519.     beginCapture();
  520.     return 1;
  521.   }
  522.   return 0;
  523. }
  524.  
  525. int FrameWnd::onMouseMove(int x, int y) {
  526.   int pos, mpos;
  527.   RECT r;
  528.  
  529.   if (!getCapture()) return 1;
  530.  
  531.   FRAMEWND_PARENT::onMouseMove(x,y);
  532.  
  533.   prevpullbarpos = pullbarpos;
  534.   
  535.   getClientRect(&r);
  536.   if (vert == DIVIDER_VERTICAL) {
  537.     pos = r.right - r.left;
  538.     mpos = x - (x % SNAP);
  539.   } else {
  540.     pos = r.bottom - r.top;
  541.     mpos = y - (y % SNAP);
  542.   }
  543.   ASSERT(pos != 0);
  544.   if (mpos < 0) mpos = 0;
  545.   if (mpos > pos) mpos = pos;
  546.  
  547.   if(divideside == SDP_FROMLEFT) {
  548.     pullbarpos = mpos;
  549.   } else {
  550.     pullbarpos = pos-mpos;
  551.   }
  552.  
  553.   if (divideside == SDP_FROMLEFT) {
  554.     if (pullbarpos < convertPropToPix(minwidth)) {
  555.       if (children[0] != NULL && children[0]->childNotify(NULL, CHILD_WINDOWSHADE_CAPABLE)) {
  556.         pullbarpos = 0;
  557.         windowshade(0, TRUE);
  558.       } else {
  559.         pullbarpos = convertPropToPix(minwidth);
  560.       }
  561.     } else {
  562.       windowshade(0, FALSE);
  563.     }
  564.   } else if (divideside == SDP_FROMRIGHT) {
  565.     if (pullbarpos < convertPropToPix(minwidth)) {
  566.       if (children[1] != NULL /* && children[1]->childNotify(NULL, CHILD_WINDOWSHADE_CAPABLE) */) {
  567.         pullbarpos = /*convertPropToPix(PULLBAR_FULL)-*/0;
  568.         windowshade(1, TRUE);
  569.       } else {
  570.         pullbarpos = convertPropToPix(PULLBAR_FULL-PULLBAR_EIGHTH);
  571.       }
  572.     } else {
  573.       windowshade(1, FALSE);
  574.     }
  575.   }
  576.  
  577.   if (!windowshaded[0] && !windowshaded[1]) {
  578. //    if (pullbarpos > pos-convertPropToPix(minwidth))
  579. //      pullbarpos = pos-convertPropToPix(minwidth);
  580.       if (pullbarpos > convertPropToPix(maxwidth))
  581.         pullbarpos = convertPropToPix(maxwidth);
  582.   }
  583.  
  584.   ASSERT(pullbarpos >= 0);
  585.  
  586.   if (pullbarpos != prevpullbarpos)
  587.     onResize();
  588.  
  589.   return 1;
  590. }
  591.  
  592. int FrameWnd::onLeftButtonUp(int x, int y) {
  593.   FRAMEWND_PARENT::onLeftButtonUp(x, y);
  594.   if (getCapture()) {
  595.     endCapture();
  596.     if (getName() != NULL) {
  597.       StringPrintf buf("FrameWnd/%s,p", getName());
  598.       api->setIntPrivate(buf, pullbarpos);
  599.     }
  600.     return 1;
  601.   }
  602.   return 0;
  603. }
  604.  
  605. int FrameWnd::onLeftButtonDblClk(int x, int y) {
  606.   screenToClient(&x, &y);
  607.   if (windowshaded[0]) {
  608.     if (vert == DIVIDER_HORIZONTAL) {
  609.       if (y < sizerRect.bottom) {
  610.         childNotify(children[0], CHILD_SETTITLEWIDTH, 128, 0);
  611.         windowshade(0, FALSE);
  612.       }
  613.     } else if (vert == DIVIDER_VERTICAL) {
  614.       if (x < sizerRect.right) {
  615.         childNotify(children[0], CHILD_SETTITLEWIDTH, 128, 0);
  616.         windowshade(0, FALSE);
  617.       }
  618.     }
  619.   }
  620.   return 1;
  621. }
  622.  
  623. void FrameWnd::windowshade(int which, int shaded) {
  624.   ASSERT(which == 0 || which == 1);
  625.   if (!!windowshaded[which] == !!shaded) return;
  626.   if (children[which] == NULL) return;
  627.   children[which]->childNotify(NULL, CHILD_WINDOWSHADE_ENABLE, shaded);
  628.   windowshaded[which] = shaded;
  629.   children[which]->setVisible(!shaded);
  630. }
  631.  
  632. BaseWnd *FrameWnd::getWindowShadedChild() {
  633.   if (nchild != 2) return NULL;
  634.   if (!(windowshaded[0] | windowshaded[1])) return NULL;
  635.   return windowshaded[0] ? children[0] : children[1];
  636. }
  637.  
  638. void FrameWnd::onSetVisible(int show) {
  639.   FRAMEWND_PARENT::onSetVisible(show);
  640.   if (children[0]) children[0]->setVisible(show);
  641.   if (children[0]) children[0]->setVisible(show);
  642. }
  643.